﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32.TaskScheduler;

namespace Swan.WakeUpLibrary
{
    public class Alarm
    {
        public static readonly string DATETIME_FORMAT_STRING = "yyyy-MM-ddTHH:mm:ss";
        private Task task;
        private string taskName;
        private TaskService taskService;
        private string userName;
        private string password;

        public Alarm(string taskName, string userName = null, string password = null)
        {
            this.taskName = taskName;
            this.userName = userName;
            this.password = password;

            this.taskService = new TaskService();
            if (!this.LoadAlarm() && userName != null && password != null)
            {
                this.CreateAlarm();
            }
        }

        public bool Run()
        {
            if (this.task == null)
                return false;
            
            var result = this.task.Run();
            return true;
        }

        public bool IsActive
        {
            get
            {
                return this.task != null && this.task.IsActive;
            }
        }

        public bool SaveAlarm(DateTime dateTime, string userName = null, string password = null)
        {
            this.userName = userName;
            this.password = password;

            var now = DateTime.Now;
            if (now.TimeOfDay > dateTime.TimeOfDay)
            {
                // Next day
                dateTime = now.Date.AddDays(1).AddHours(dateTime.Hour).AddMinutes(dateTime.Minute);
            }
            else
            {
                dateTime = now.Date.AddHours(dateTime.Hour).AddMinutes(dateTime.Minute);
            }

            if (task == null)
            {
                this.CreateAlarm();
            }

            task.Definition.Triggers.Clear();
            task.Definition.Triggers.Add(new TimeTrigger(dateTime));

            //Actions
            task.Definition.Actions.Clear();
            var ass = System.Reflection.Assembly.GetEntryAssembly();
            task.Definition.Actions.Add(new ExecAction(ass.Location, " -a Default"));

            return this.RegisterTask(task.Definition);
        }

        private void CreateAlarm()
        {
            // Create a new task definition and assign properties
            TaskDefinition td = this.taskService.NewTask();
            td.RegistrationInfo.Description = "Used for swan wake upp application, do not remove.";
            td.RegistrationInfo.Author = "SwanWakeUp";
            td.Settings.AllowDemandStart = true;
            td.Settings.DisallowStartIfOnBatteries = false;
            td.Settings.StopIfGoingOnBatteries = false;
            td.Settings.DisallowStartIfOnBatteries = false;
            td.Settings.StopIfGoingOnBatteries = false;
            td.Settings.StartWhenAvailable = true;

            this.RegisterTask(td);
        }

        private bool RegisterTask(TaskDefinition td)
        {
            bool passwordTask = this.userName != null && this.password != null;

            td.Principal.LogonType = passwordTask ? TaskLogonType.InteractiveTokenOrPassword : TaskLogonType.InteractiveToken;
            td.RegistrationInfo.Author = "Johan";
            td.RegistrationInfo.Description = "Demo";
            td.Settings.WakeToRun = passwordTask;
            td.Settings.Priority = passwordTask ? System.Diagnostics.ProcessPriorityClass.High : System.Diagnostics.ProcessPriorityClass.Normal;

            if (passwordTask)
            {
                this.task = (this.taskService.RootFolder.RegisterTaskDefinition(this.taskName, td, TaskCreation.CreateOrUpdate, userName, password, TaskLogonType.Password));
            }
            else
            {    
                this.task = this.taskService.RootFolder.RegisterTaskDefinition(this.taskName, td);
            }
            return this.task != null;
        }

        private bool LoadAlarm()
        {
            this.task = this.taskService.GetTask(this.taskName);
            if (this.task == null)
                return false;

            return true;
        }

        public DateTime? GetStartTime(bool reload = false)
        {
            if (this.task == null || reload)
                if (!this.LoadAlarm())
                    return null;

            if (!this.task.Enabled)
                return null;

            var timeTrigger = this.task.Definition.Triggers.Where(t => t is TimeTrigger && ((TimeTrigger)t).StartBoundary > DateTime.Now).FirstOrDefault();

            return timeTrigger == null ? null : (DateTime?)timeTrigger.StartBoundary;
        }

        public void Kill()
        {
            this.task.Stop();
        }
    }
}
